/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include "flgrCoreMalloc.h"
#include "flgrCoreDispatch.h"
#include "flgrCoreCopy.h"
#include "flgrCoreIO.h"
#include "flgrCoreSlideWindow.h"
#include "flgrCoreNhbFill.h"
#include "flgrCoreNhbManage.h"
#include "flgrCoreDataIO.h"
#include "flgrCoreVector.h"
#include "flgrCoreShear.h"

/*!
 * \defgroup group_fulguro_core_slide Sliding Window
 * \ingroup group_fulguro_core
 * \brief Main functions to slide every kernel and every computation over FLGR_Data2D.
 * <BR>
 * If source and destination are the same, "raster" ("anti_raster") functions will modify Neighborhood
 * definition to comply with a recursive raster (resp. anti_raster) scan way.
 * \image html nhb_8c.png "A standard neighborhood definition (center in light gray)"
 * \image latex nhb_8c.eps "A standard neighborhood definition (center in light gray)"
 * <BR>
 * \image html nhb_8c_raster.png "Redefined neighborhood definition for recursive raster scan"
 * \image latex nhb_8c_raster.eps "Redefined neighborhood definition for recursive raster scan"
 * <BR>
 * \image html nhb_8c_antiraster.png "Redefined neighborhood definition for recursive anti_raster scan" 
 * \image latex nhb_8c_antiraster.eps "Redefined neighborhood definition for recursive anti_raster scan"
 * <BR>
 * Neighborhoods definitions and Images are created in the same way. For Mathematical Morphology, values
 * inside a neighborhood represent which neighbors are taken into account. For Linear processing, values
 * represent coefficient filter ...<BR>
 * The 6-connexity is emulated by processing odd and even rows with differents 8-connexity neighborhoods
 * definitions. A specific function called "flgr2d_fill_nhb_even_rows" allows to fill even neighborhood
 * from an odd one.<BR><BR>
 * \image html mesh_6_8.png "6-connexity mesh emulation throw 8-connexity" 
 * \image latex mesh_6_8.eps "6-connexity mesh emulation throw 8-connexity"<BR>
 * Note that a neighborhood must be represented by the user in the even way (in blue in the previous figure)<BR>
 * <BR><BR>
 * A C function to define computation over an extracted neighborhood could be define as follow :<BR><BR>
 * \code //minimum over an extracted neighborhood of an image
 * void flgr2d_get_nhb_minimum_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
 *   int i,k;
 *   int spp = extr->spp;
 *   dtype *presult = (dtype *) result->array;
 *   dtype *list_data_val;
 *   int *size = extr->size;
 *   dtype mini;
 *
 *   for(k=0 ; k<spp ; k++) {	// for each channel					
 *     list_data_val = (dtype *) extr->list_data_val[k]; 
 *     mini = list_data_val[0]; 
 *     for(i=1 ; i<size[k] ; i++){ // for each neighbor, find minimum
 *       mini = mini < list_data_val[i] ? mini : list_data_val[i];
 *     }
 *     flgr_set_array_##dtype(presult,k,mini); //store minimum in vector result
 *   }
 * }
 * \endcode
 *
 * To define an erode function using the previous kernel operation:
 * \code
 * void flgr2d_erode_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb) {
 *   flgr2d_raster_slide_window_fgUINT8(imgdest, imgsrc, nhb, FLGR_NHB_NO_SYM, flgr_get_nhb_minimum_fgUINT8);
 * }
 * \endcode
 * @{
 */


////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(dtype,get_nhb_op)	\
  FLGR_Vector *result;						\
  FLGR_Data1D *nhbrs;						\
  FLGR_NhbBox1D *extr;						\
  dtype *vector_array;						\
  dtype *data_array;						\
  int j,w, spp = datsrc->spp;					\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  w=datsrc->length;						\
								\
  result = flgr_vector_create(datsrc->spp,datsrc->type);	\
								\
  vector_array = (dtype *) result->array;			\
  data_array = (dtype *) datdest->array;			\
								\
  extr = flgr1d_create_neighbor_box(nhb);			\
								\
  nhbrs=flgr1d_create_neighborhood_from(nhb);			\
								\
  if(nhb_sym==FLGR_NHB_SYM)					\
    flgr1d_mirror_##dtype(nhbrs,nhb);				\
  else								\
    flgr1d_copy_##dtype##_##dtype(nhbrs,nhb);			\
 								\
  if(datdest==datsrc) {						\
    flgr1d_apply_raster_scan_method_##dtype(nhbrs);		\
  }								\
								\
  for(j=0 ; j<w ; j++) {					\
								\
    get_nhb_op##_##dtype(extr,datsrc,nhbrs,j);			\
								\
    (*computeNhb)(result,extr);					\
      								\
    flgr_set_data_array_vector_##dtype(data_array,		\
				       vector_array,		\
				       spp,j);			\
    								\
  }								\
								\
  flgr1d_destroy(nhbrs);					\
  flgr1d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
								\
  return

  
////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(dtype,get_nhb_op)	\
  FLGR_Vector *result;						\
  FLGR_Data1D *nhbars;						\
  FLGR_NhbBox1D *extr;						\
  dtype *vector_array;						\
  dtype *data_array;						\
  int j,w, spp = datsrc->spp;					\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  w=datsrc->length;						\
								\
  result = flgr_vector_create(spp,datsrc->type);		\
								\
  vector_array = (dtype *) result->array;			\
  data_array = (dtype *) datdest->array;			\
								\
  extr = flgr1d_create_neighbor_box(nhb);			\
								\
  nhbars=flgr1d_create_neighborhood_from(nhb);			\
								\
  if(nhb_sym==FLGR_NHB_SYM)					\
    flgr1d_mirror_##dtype(nhbars,nhb);				\
  else								\
    flgr1d_copy_##dtype##_##dtype(nhbars,nhb);			\
								\
  if(datdest==datsrc) {						\
    flgr1d_apply_anti_raster_scan_method_##dtype(nhbars);	\
  }								\
								\
  for(j=w-1 ; j>=0 ; j--) {					\
								\
    get_nhb_op##_##dtype(extr,datsrc,nhbars,j);			\
								\
    (*computeNhb)(result,extr);					\
      								\
    flgr_set_data_array_vector_##dtype(data_array,		\
				       vector_array,		\
				       spp,j);			\
								\
  }								\
								\
  flgr1d_destroy(nhbars);					\
  flgr1d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
								\
  return

  
////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr1d_raster_slide_window_before_op_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(dtype)	\
  FLGR_Vector *result,*vec_arith;				\
  FLGR_Data1D *nhbrs;						\
  FLGR_NhbBox1D *extr;						\
  dtype *vector_array;						\
  dtype *vector_arith_array;					\
  dtype *data_array;						\
  dtype *data_arith_array;					\
  int j, spp = datsrc->spp;					\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  result = flgr_vector_create(datsrc->spp,datsrc->type);	\
  vec_arith = flgr_vector_create(datsrc->spp,datsrc->type);	\
								\
  vector_array = (dtype *) result->array;			\
  vector_arith_array = (dtype *) vec_arith->array;		\
  data_array = (dtype *) datdest->array;			\
  data_arith_array = (dtype *) datarith->array;			\
								\
  extr = flgr1d_create_neighbor_box(nhb);			\
								\
  nhbrs=flgr1d_create_neighborhood_from(nhb);			\
 								\
  if(nhb_sym==FLGR_NHB_SYM)					\
    flgr1d_mirror_##dtype(nhbrs,nhb);				\
  else								\
    flgr1d_copy_##dtype##_##dtype(nhbrs,nhb);			\
								\
  if(datdest==datsrc) {						\
    flgr1d_apply_raster_scan_method_##dtype(nhbrs);		\
  }								\
								\
  for(j=0 ; j<datsrc->length ; j++) {				\
								\
    flgr1d_get_neighborhood_##dtype(extr,datsrc,nhbrs,j);	\
								\
    (*computeNhb)(result,extr);					\
								\
    flgr_get_data_array_vector_##dtype(vector_arith_array,	\
				       data_arith_array,	\
				       spp,j);			\
								\
    (*computeArith)(result,result,vec_arith);			\
								\
    flgr_set_data_array_vector_##dtype(data_array,		\
				       vector_array,		\
				       spp,j);			\
     								\
  }								\
								\
  flgr1d_destroy(nhbrs);					\
  flgr1d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
  flgr_vector_destroy(vec_arith);				\
								\
  return

////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr1d_anti_raster_slide_window_before_op_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(dtype)	\
  FLGR_Vector *result,*vec_arith;				\
  FLGR_Data1D *nhbars;						\
  FLGR_NhbBox1D *extr;						\
  dtype *vector_array;						\
  dtype *vector_arith_array;					\
  dtype *data_array;						\
  dtype *data_arith_array;					\
  int j, spp = datsrc->spp;					\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  result = flgr_vector_create(datsrc->spp,datsrc->type);	\
  vec_arith = flgr_vector_create(datsrc->spp,datsrc->type);	\
								\
  vector_array = (dtype *) result->array;			\
  vector_arith_array = (dtype *) vec_arith->array;		\
  data_array = (dtype *) datdest->array;			\
  data_arith_array = (dtype *) datarith->array;			\
								\
  extr = flgr1d_create_neighbor_box(nhb);			\
								\
  nhbars=flgr1d_create_neighborhood_from(nhb);			\
 								\
  if(nhb_sym==FLGR_NHB_SYM)					\
    flgr1d_mirror_##dtype(nhbars,nhb);				\
  else								\
    flgr1d_copy_##dtype##_##dtype(nhbars,nhb);			\
								\
  if(datdest==datsrc) {						\
    flgr1d_apply_raster_scan_method_##dtype(nhbars);		\
  }								\
								\
  for(j=datsrc->length-1 ; j>=0 ; j--) {			\
								\
    flgr1d_get_neighborhood_##dtype(extr,datsrc,nhbars,j);	\
								\
    (*computeNhb)(result,extr);					\
								\
    flgr_get_data_array_vector_##dtype(vector_arith_array,	\
				       data_arith_array,	\
				       spp,j);			\
								\
    (*computeArith)(result,result,vec_arith);			\
								\
    flgr_set_data_array_vector_##dtype(data_array,		\
				       vector_array,		\
				       spp,j);			\
     								\
  }								\
								\
  flgr1d_destroy(nhbars);					\
  flgr1d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
  flgr_vector_destroy(vec_arith);				\
								\
  return



void flgr1d_raster_slide_window_fgBIT(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
				      FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgBIT,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgUINT8(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
					FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT8,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgUINT16(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb, int nhb_sym,
					 FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT16,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					 FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
				       FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT8,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT16,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					  FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgFLOAT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_window_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					  FLGR_ComputeNhb1D computeNhb) { 
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgFLOAT64,flgr1d_get_neighborhood);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data1D in a raster scan way
 *  @param datdest : pointer to destination image
 *  @param datsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_raster_slide_window(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
				    FLGR_ComputeNhb1D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr1d_is_data_same_type(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr1d_is_data_same_spp(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_raster_slide_window,datdest,datsrc,nhb,nhb_sym,computeNhb);

}










void flgr1d_anti_raster_slide_window_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					   FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgBIT,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					     FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT8,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					      FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT16,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					      FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT32,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					    FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT8,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym, 
					     FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT16,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
					     FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT32,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym,
					       FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgFLOAT32,flgr1d_get_neighborhood);
}
void flgr1d_anti_raster_slide_window_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym,
					       FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgFLOAT64,flgr1d_get_neighborhood);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data1D in a anti_raster scan way
 *  @param datdest : pointer to destination image
 *  @param datsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_anti_raster_slide_window(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,
					 int nhb_sym, FLGR_ComputeNhb1D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr1d_is_data_same_type(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr1d_is_data_same_spp(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_anti_raster_slide_window,datdest,datsrc,nhb,nhb_sym,computeNhb);

}




void flgr1d_raster_slide_window_unfolded_fgBIT(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
					       FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgBIT,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgUINT8(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
						 FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT8,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgUINT16(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb, int nhb_sym,
						  FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT16,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						  FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgUINT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT8,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						 FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT16,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						 FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgINT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						   FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgFLOAT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_raster_slide_window_unfolded_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						   FLGR_ComputeNhb1D computeNhb) { 
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D(fgFLOAT64,flgr1d_get_neighborhood_unfolded);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data1D in a raster scan way
 *  @param datdest : pointer to destination image
 *  @param datsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_raster_slide_window_unfolded(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,int nhb_sym,
					     FLGR_ComputeNhb1D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr1d_is_data_same_type(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr1d_is_data_same_spp(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_raster_slide_window_unfolded,datdest,datsrc,nhb,nhb_sym,computeNhb);

}










void flgr1d_anti_raster_slide_window_unfolded_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						    FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgBIT,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						      FLGR_ComputeNhb1D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT8,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						       FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT16,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						       FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgUINT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						     FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT8,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym, 
						      FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT16,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb, int nhb_sym,
						      FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgINT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym,
							FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgFLOAT32,flgr1d_get_neighborhood_unfolded);
}
void flgr1d_anti_raster_slide_window_unfolded_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *nhb,int nhb_sym,
							FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D(fgFLOAT64,flgr1d_get_neighborhood_unfolded);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data1D in a anti_raster scan way
 *  @param datdest : pointer to destination image
 *  @param datsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_anti_raster_slide_window_unfolded(FLGR_Data1D *datdest,FLGR_Data1D *datsrc,FLGR_Data1D *nhb,
						  int nhb_sym, FLGR_ComputeNhb1D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr1d_is_data_same_type(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr1d_is_data_same_spp(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_anti_raster_slide_window_unfolded,datdest,datsrc,nhb,nhb_sym,computeNhb);

}











void flgr1d_raster_slide_window_before_op_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						int nhb_sym,
						FLGR_ComputeNhb1D computeNhb,
						FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgBIT);
}

void flgr1d_raster_slide_window_before_op_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb1D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT8);
}

void flgr1d_raster_slide_window_before_op_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						   int nhb_sym,
						   FLGR_ComputeNhb1D computeNhb,
						   FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT16);
}

void flgr1d_raster_slide_window_before_op_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						   int nhb_sym,
						   FLGR_ComputeNhb1D computeNhb,
						   FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT32);
}

void flgr1d_raster_slide_window_before_op_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						 int nhb_sym,
						 FLGR_ComputeNhb1D computeNhb,
						 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT8);
}

void flgr1d_raster_slide_window_before_op_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb1D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT16);
}

void flgr1d_raster_slide_window_before_op_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb1D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT32);
}

void flgr1d_raster_slide_window_before_op_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						    int nhb_sym,
						    FLGR_ComputeNhb1D computeNhb,
						    FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgFLOAT32);
}

void flgr1d_raster_slide_window_before_op_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						    int nhb_sym,
						    FLGR_ComputeNhb1D computeNhb,
						    FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgFLOAT64);
}




void flgr1d_anti_raster_slide_window_before_op_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						     int nhb_sym,
						     FLGR_ComputeNhb1D computeNhb,
						     FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgBIT);
}

void flgr1d_anti_raster_slide_window_before_op_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb1D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT8);
}

void flgr1d_anti_raster_slide_window_before_op_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
							int nhb_sym,
							FLGR_ComputeNhb1D computeNhb,
							FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT16);
}

void flgr1d_anti_raster_slide_window_before_op_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
							int nhb_sym,
							FLGR_ComputeNhb1D computeNhb,
							FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgUINT32);
}

void flgr1d_anti_raster_slide_window_before_op_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						      int nhb_sym,
						      FLGR_ComputeNhb1D computeNhb,
						      FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT8 );
}

void flgr1d_anti_raster_slide_window_before_op_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb1D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT16);
}

void flgr1d_anti_raster_slide_window_before_op_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb1D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgINT32);
}

void flgr1d_anti_raster_slide_window_before_op_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
							 int nhb_sym,
							 FLGR_ComputeNhb1D computeNhb,
							 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgFLOAT32);
}

void flgr1d_anti_raster_slide_window_before_op_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, FLGR_Data1D *datarith, FLGR_Data1D *nhb,
							 int nhb_sym,
							 FLGR_ComputeNhb1D computeNhb,
							 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_1D_BEFORE_OP(fgFLOAT64);
}
























////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(dtype,get_nhb_op)	\
  int i,j,w,h,spp = imgsrc->spp;				\
  dtype *vector_array;						\
  dtype *data_array;						\
  FLGR_Vector *result;						\
  FLGR_Data2D *nhbEven,*nhbOdd,*nhbrs;				\
  FLGR_NhbBox2D *extr;						\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  w=imgsrc->size_x;						\
  h=imgsrc->size_y;						\
								\
  result = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
								\
  vector_array = (dtype *) result->array;			\
								\
  extr = flgr2d_create_neighbor_box(nhb);			\
								\
  nhbEven=flgr2d_create_neighborhood_from(nhb);			\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);			\
								\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,nhb_sym);	\
								\
  if(imgdest==imgsrc) {						\
    flgr2d_apply_raster_scan_method_##dtype(nhbOdd);		\
    flgr2d_apply_raster_scan_method_##dtype(nhbEven);		\
  }								\
								\
  for(i=0 ; i<h; i++) {						\
								\
    data_array = (dtype *) (imgdest->array[i]);			\
								\
    for(j=0 ; j<w ; j++) {					\
								\
      nhbrs = (((i%2)==1) ? nhbOdd : nhbEven);			\
								\
      get_nhb_op##_##dtype(extr,imgsrc,nhbrs,i,j);		\
								\
      (*computeNhb)(result,extr);				\
      								\
      flgr_set_data_array_vector_##dtype(data_array,		\
					 vector_array,		\
					 spp,j);		\
    }								\
  }								\
								\
  flgr2d_destroy(nhbOdd);					\
  flgr2d_destroy(nhbEven);					\
  flgr2d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
								\
  return

  


////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_anti_raster_slide_window_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(dtype,get_nhb_op)	\
  int i,j,w,h,spp = imgsrc->spp;				\
  dtype *vector_array;						\
  dtype *data_array;						\
  FLGR_Vector *result;						\
  FLGR_Data2D *nhbars;						\
  FLGR_Data2D *nhbEven,*nhbOdd;					\
  FLGR_NhbBox2D *extr;						\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  w=imgsrc->size_x;						\
  h=imgsrc->size_y;						\
								\
  result = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
								\
  vector_array = (dtype *) result->array;			\
								\
  extr = flgr2d_create_neighbor_box(nhb);			\
								\
  nhbEven=flgr2d_create_neighborhood_from(nhb);			\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);			\
								\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,nhb_sym);	\
								\
  if(imgdest==imgsrc) {						\
    flgr2d_apply_anti_raster_scan_method_##dtype(nhbOdd);	\
    flgr2d_apply_anti_raster_scan_method_##dtype(nhbEven);	\
  }								\
								\
  for(i=h-1 ; i>=0 ; i--) {					\
								\
    data_array = (dtype *) (imgdest->array[i]);			\
								\
    for(j=w-1 ; j>=0 ; j--) {					\
								\
      nhbars = (((i%2)==1) ? nhbOdd : nhbEven);			\
								\
      get_nhb_op##_##dtype(extr,imgsrc,nhbars,i,j);		\
								\
      (*computeNhb)(result,extr);				\
								\
      flgr_set_data_array_vector_##dtype(data_array,		\
					 vector_array,		\
					 spp,j);		\
      								\
    }								\
  }								\
								\
  flgr2d_destroy(nhbOdd);					\
  flgr2d_destroy(nhbEven);					\
  flgr_vector_destroy(result);					\
  flgr2d_destroy_neighbor_box(extr);				\
								\
  return


////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_before_op_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(dtype)	\
  int i,j;							\
  FLGR_Vector *result,*vec_arith;				\
  FLGR_Data2D *nhbrs;						\
  FLGR_Data2D *nhbEven,*nhbOdd;					\
  FLGR_NhbBox2D *extr;						\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  result = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
  vec_arith = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
								\
  extr = flgr2d_create_neighbor_box(nhb);			\
								\
  nhbEven=flgr2d_create_neighborhood_from(nhb);			\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);			\
								\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,nhb_sym);	\
								\
  if(imgdest==imgsrc) {						\
    flgr2d_apply_raster_scan_method_##dtype(nhbOdd);		\
    flgr2d_apply_raster_scan_method_##dtype(nhbEven);		\
  }								\
								\
  for(i=0 ; i<imgsrc->size_y ; i++) {				\
    for(j=0 ; j<imgsrc->size_x ; j++) {				\
								\
      nhbrs = (((i%2)==1) ? nhbOdd : nhbEven);			\
								\
      flgr2d_get_neighborhood_##dtype(extr,imgsrc,nhbrs,i,j);	\
								\
      (*computeNhb)(result,extr);				\
								\
      flgr2d_get_data_vector_##dtype(imgarith,i,j,vec_arith);	\
								\
      (*computeArith)(result,result,vec_arith);			\
								\
      flgr2d_set_data_vector_##dtype(imgdest,i,j,result);	\
     								\
    }								\
  }								\
								\
  flgr2d_destroy(nhbOdd);					\
  flgr2d_destroy(nhbEven);					\
  flgr2d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(result);					\
  flgr_vector_destroy(vec_arith);				\
								\
  return

////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_anti_raster_slide_window_before_op_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(dtype)	\
  int i,j;							\
  FLGR_Vector *result,*vec_arith;				\
  FLGR_Data2D *nhbars;						\
  FLGR_Data2D *nhbEven,*nhbOdd;					\
  FLGR_NhbBox2D *extr;						\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  result = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
  vec_arith = flgr_vector_create(imgsrc->spp,imgsrc->type);	\
								\
  extr = flgr2d_create_neighbor_box(nhb);			\
								\
  nhbEven=flgr2d_create_neighborhood_from(nhb);			\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);			\
								\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,nhb_sym);	\
								\
  if(imgdest==imgsrc) {						\
    flgr2d_apply_anti_raster_scan_method_##dtype(nhbOdd);	\
    flgr2d_apply_anti_raster_scan_method_##dtype(nhbEven);	\
  }								\
								\
  for(i=imgsrc->size_y-1 ; i>=0 ; i--) {			\
    for(j=imgsrc->size_x-1 ; j>=0 ; j--) {			\
								\
      nhbars = (((i%2)==1) ? nhbOdd : nhbEven);			\
								\
      flgr2d_get_neighborhood_##dtype(extr,imgsrc,nhbars,i,j);	\
								\
      (*computeNhb)(result,extr);				\
 								\
      flgr2d_get_data_vector_##dtype(imgarith,i,j,vec_arith);	\
								\
      (*computeArith)(result,result,vec_arith);			\
 								\
      flgr2d_set_data_vector_##dtype(imgdest,i,j,result);	\
      								\
    }								\
  }								\
								\
  flgr2d_destroy(nhbOdd);					\
  flgr2d_destroy(nhbEven);					\
  flgr2d_destroy_neighbor_box(extr);				\
  flgr_vector_destroy(vec_arith);				\
  flgr_vector_destroy(result);					\
								\
  return





void flgr2d_raster_slide_window_fgBIT(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
				      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgBIT,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgUINT8(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
					FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT8,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgUINT16(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb, int nhb_sym,
					 FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT16,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					 FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
				       FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT8,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT16,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					  FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgFLOAT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_window_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					  FLGR_ComputeNhb2D computeNhb) { 
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgFLOAT64,flgr2d_get_neighborhood);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data2D in a raster scan way
 *  @param imgdest : pointer to destination image
 *  @param imgsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_raster_slide_window(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
				    FLGR_ComputeNhb2D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(imgdest,imgsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr2d_is_data_same_type(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr2d_is_data_same_spp(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_raster_slide_window,imgdest,imgsrc,nhb,nhb_sym,computeNhb);

}










void flgr2d_anti_raster_slide_window_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					   FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgBIT,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					     FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT8,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT16,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT32,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					    FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT8,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym, 
					     FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT16,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
					     FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT32,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym,
					       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgFLOAT32,flgr2d_get_neighborhood);
}
void flgr2d_anti_raster_slide_window_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym,
					       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgFLOAT64,flgr2d_get_neighborhood);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data2D in a anti_raster scan way
 *  @param imgdest : pointer to destination image
 *  @param imgsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_anti_raster_slide_window(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,
					 int nhb_sym, FLGR_ComputeNhb2D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(imgdest,imgsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr2d_is_data_same_type(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr2d_is_data_same_spp(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_anti_raster_slide_window,imgdest,imgsrc,nhb,nhb_sym,computeNhb);

}









void flgr2d_raster_slide_window_unfolded_fgBIT(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
					       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgBIT,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgUINT8(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
						 FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT8,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgUINT16(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb, int nhb_sym,
						  FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT16,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						  FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgUINT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT8,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						 FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT16,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						 FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgINT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						   FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgFLOAT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_raster_slide_window_unfolded_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						   FLGR_ComputeNhb2D computeNhb) { 
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D(fgFLOAT64,flgr2d_get_neighborhood_unfolded);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data2D in a raster scan way
 *  @param imgdest : pointer to destination image
 *  @param imgsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_raster_slide_window_unfolded(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,int nhb_sym,
					     FLGR_ComputeNhb2D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(imgdest,imgsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr2d_is_data_same_type(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr2d_is_data_same_spp(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_raster_slide_window_unfolded,imgdest,imgsrc,nhb,nhb_sym,computeNhb);

}










void flgr2d_anti_raster_slide_window_unfolded_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						    FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgBIT,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						      FLGR_ComputeNhb2D computeNhb){
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT8,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT16,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgUINT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						     FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT8,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym, 
						      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT16,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb, int nhb_sym,
						      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgINT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym,
							FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgFLOAT32,flgr2d_get_neighborhood_unfolded);
}
void flgr2d_anti_raster_slide_window_unfolded_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb,int nhb_sym,
							FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D(fgFLOAT64,flgr2d_get_neighborhood_unfolded);
}


////////////////////////////////////////////////////////////////////////////
/*! Slide a computation kernel on a FLGR_Data2D in a anti_raster scan way
 *  @param imgdest : pointer to destination image
 *  @param imgsrc : pointer to source image
 *  @param nhb : pointer to neighborhood definition or convolution kernel definition
 *  @param nhb_sym : flag to specify if the given Nhb must be symetrized (FLGR_NHB_SYM, FLGR_NHB_NO_SYM)
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_anti_raster_slide_window_unfolded(FLGR_Data2D *imgdest,FLGR_Data2D *imgsrc,FLGR_Data2D *nhb,
						  int nhb_sym, FLGR_ComputeNhb2D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(imgdest,imgsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if((ret=flgr2d_is_data_same_type(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr2d_is_data_same_spp(imgdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_anti_raster_slide_window_unfolded,imgdest,imgsrc,nhb,nhb_sym,computeNhb);

}













void flgr2d_raster_slide_window_before_op_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						int nhb_sym,
						FLGR_ComputeNhb2D computeNhb,
						FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgBIT);
}

void flgr2d_raster_slide_window_before_op_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb2D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT8);
}

void flgr2d_raster_slide_window_before_op_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						   int nhb_sym,
						   FLGR_ComputeNhb2D computeNhb,
						   FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT16);
}

void flgr2d_raster_slide_window_before_op_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						   int nhb_sym,
						   FLGR_ComputeNhb2D computeNhb,
						   FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT32);
}

void flgr2d_raster_slide_window_before_op_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						 int nhb_sym,
						 FLGR_ComputeNhb2D computeNhb,
						 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT8);
}

void flgr2d_raster_slide_window_before_op_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb2D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT16);
}

void flgr2d_raster_slide_window_before_op_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						  int nhb_sym,
						  FLGR_ComputeNhb2D computeNhb,
						  FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT32);
}

void flgr2d_raster_slide_window_before_op_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						    int nhb_sym,
						    FLGR_ComputeNhb2D computeNhb,
						    FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgFLOAT32);
}

void flgr2d_raster_slide_window_before_op_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						    int nhb_sym,
						    FLGR_ComputeNhb2D computeNhb,
						    FLGR_ComputeArith computeArith) {
  FLGR_MACRO_RASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgFLOAT64);
}




void flgr2d_anti_raster_slide_window_before_op_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						     int nhb_sym,
						     FLGR_ComputeNhb2D computeNhb,
						     FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgBIT);
}

void flgr2d_anti_raster_slide_window_before_op_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb2D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT8);
}

void flgr2d_anti_raster_slide_window_before_op_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
							int nhb_sym,
							FLGR_ComputeNhb2D computeNhb,
							FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT16);
}

void flgr2d_anti_raster_slide_window_before_op_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
							int nhb_sym,
							FLGR_ComputeNhb2D computeNhb,
							FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgUINT32);
}

void flgr2d_anti_raster_slide_window_before_op_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						      int nhb_sym,
						      FLGR_ComputeNhb2D computeNhb,
						      FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT8 );
}

void flgr2d_anti_raster_slide_window_before_op_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb2D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT16);
}

void flgr2d_anti_raster_slide_window_before_op_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
						       int nhb_sym,
						       FLGR_ComputeNhb2D computeNhb,
						       FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgINT32);
}

void flgr2d_anti_raster_slide_window_before_op_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
							 int nhb_sym,
							 FLGR_ComputeNhb2D computeNhb,
							 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgFLOAT32);
}

void flgr2d_anti_raster_slide_window_before_op_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *imgarith, FLGR_Data2D *nhb,
							 int nhb_sym,
							 FLGR_ComputeNhb2D computeNhb,
							 FLGR_ComputeArith computeArith) {
  FLGR_MACRO_ANTIRASTER_SLIDE_WINDOW_2D_BEFORE_OP(fgFLOAT64);
}










#define FLGR_APPLY_RASTER_SCAN_METHOD(dtype)				\
  FLGR_Vector *vec = flgr_vector_create(nhb->spp,nhb->type);		\
  int j;								\
  int w = nhb->length;							\
 									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_populate_from_scalar_##dtype(vec,0);			\
									\
  for(j=(w/2+1);j<w;j++) flgr1d_set_data_vector_##dtype(nhb,j,vec);	\
									\
  flgr_vector_destroy(vec);						\
									\
  return

void flgr1d_apply_raster_scan_method_fgBIT(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgBIT);
}
void flgr1d_apply_raster_scan_method_fgUINT8(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgUINT8);
}
void flgr1d_apply_raster_scan_method_fgUINT16(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgUINT16);
}
void flgr1d_apply_raster_scan_method_fgUINT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgUINT32);
}
void flgr1d_apply_raster_scan_method_fgINT8(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgINT8);
}
void flgr1d_apply_raster_scan_method_fgINT16(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgINT16);
}
void flgr1d_apply_raster_scan_method_fgINT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgINT32);
}
void flgr1d_apply_raster_scan_method_fgFLOAT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgFLOAT32);
}
void flgr1d_apply_raster_scan_method_fgFLOAT64(FLGR_Data1D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Apply a raster scan method on a neighborhood definition.
 *  Some nhb values are unset to satisfy the raster scan order
 *  @param nhb : a pointer to FLGR_Data1D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_apply_raster_scan_method(FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr1d_apply_raster_scan_method,nhb);
}





#define FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(dtype)			\
  FLGR_Vector *vec = flgr_vector_create(nhb->spp,nhb->type);		\
  int j;								\
  int w = nhb->length;							\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_populate_from_scalar_##dtype(vec,0);			\
									\
  for(j=0;j<w/2;j++) flgr1d_set_data_vector_##dtype(nhb,j,vec);		\
									\
  flgr_vector_destroy(vec);						\
									\
  return 

void flgr1d_apply_anti_raster_scan_method_fgBIT(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgBIT);
}
void flgr1d_apply_anti_raster_scan_method_fgUINT8(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgUINT8);
}
void flgr1d_apply_anti_raster_scan_method_fgUINT16(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgUINT16);
}
void flgr1d_apply_anti_raster_scan_method_fgUINT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgUINT32);
}
void flgr1d_apply_anti_raster_scan_method_fgINT8(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgINT8);
}
void flgr1d_apply_anti_raster_scan_method_fgINT16(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgINT16);
}
void flgr1d_apply_anti_raster_scan_method_fgINT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgINT32);
}
void flgr1d_apply_anti_raster_scan_method_fgFLOAT32(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgFLOAT32);
}
void flgr1d_apply_anti_raster_scan_method_fgFLOAT64(FLGR_Data1D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_1D(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Apply a anti_raster scan method on a neighborhood definition.
 *  Some nhb values are unset to satisfy the anti_raster scan order
 *  @param nhb : a pointer to FLGR_Data1D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_apply_anti_raster_scan_method(FLGR_Data1D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr1d_apply_anti_raster_scan_method,nhb);
}









#define FLGR_APPLY_RASTER_SCAN_METHOD_2D(dtype)				\
  FLGR_Vector *vec = flgr_vector_create(nhb->spp,nhb->type);		\
  int i,j;								\
  int w = nhb->size_x;							\
  int h = nhb->size_y;							\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_populate_from_scalar_##dtype(vec,0);			\
									\
  for(j=(w/2+1);j<w;j++) flgr2d_set_data_vector_##dtype(nhb,h/2,j,vec);	\
									\
  for(i = (h/2)+1 ; i<h ; i++) {					\
    for(j=0;j<w;j++) flgr2d_set_data_vector_##dtype(nhb,i,j,vec);	\
  }									\
									\
  flgr_vector_destroy(vec);						\
									\
  return

void flgr2d_apply_raster_scan_method_fgBIT(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgBIT);
}
void flgr2d_apply_raster_scan_method_fgUINT8(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgUINT8);
}
void flgr2d_apply_raster_scan_method_fgUINT16(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgUINT16);
}
void flgr2d_apply_raster_scan_method_fgUINT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgUINT32);
}
void flgr2d_apply_raster_scan_method_fgINT8(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgINT8);
}
void flgr2d_apply_raster_scan_method_fgINT16(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgINT16);
}
void flgr2d_apply_raster_scan_method_fgINT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgINT32);
}
void flgr2d_apply_raster_scan_method_fgFLOAT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgFLOAT32);
}
void flgr2d_apply_raster_scan_method_fgFLOAT64(FLGR_Data2D *nhb) {
  FLGR_APPLY_RASTER_SCAN_METHOD_2D(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Apply a raster scan method on a neighborhood definition.
 *  Some nhb values are unset to satisfy the raster scan order
 *  @param nhb : a pointer to FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_apply_raster_scan_method(FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_apply_raster_scan_method,nhb);
}





#define FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(dtype)			\
  FLGR_Vector *vec = flgr_vector_create(nhb->spp,nhb->type);		\
  int i,j;								\
  int w = nhb->size_x;							\
  int h = nhb->size_y;							\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_populate_from_scalar_##dtype(vec,0);			\
									\
  for(j=0;j<w/2;j++) flgr2d_set_data_vector_##dtype(nhb,h/2,j,vec);	\
									\
  for(i = 0 ; i<h/2 ; i++) {						\
    for(j=0;j<w;j++) flgr2d_set_data_vector_##dtype(nhb,i,j,vec);	\
  }									\
									\
  flgr_vector_destroy(vec);						\
									\
  return 

void flgr2d_apply_anti_raster_scan_method_fgBIT(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgBIT);
}
void flgr2d_apply_anti_raster_scan_method_fgUINT8(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgUINT8);
}
void flgr2d_apply_anti_raster_scan_method_fgUINT16(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgUINT16);
}
void flgr2d_apply_anti_raster_scan_method_fgUINT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgUINT32);
}
void flgr2d_apply_anti_raster_scan_method_fgINT8(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgINT8);
}
void flgr2d_apply_anti_raster_scan_method_fgINT16(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgINT16);
}
void flgr2d_apply_anti_raster_scan_method_fgINT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgINT32);
}
void flgr2d_apply_anti_raster_scan_method_fgFLOAT32(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgFLOAT32);
}
void flgr2d_apply_anti_raster_scan_method_fgFLOAT64(FLGR_Data2D *nhb) {
  FLGR_APPLY_ANTIRASTER_SCAN_METHOD_2D(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Apply a anti_raster scan method on a neighborhood definition.
 *  Some nhb values are unset to satisfy the anti_raster scan order
 *  @param nhb : a pointer to FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_apply_anti_raster_scan_method(FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_apply_anti_raster_scan_method,nhb);
}

















////////////////////////////////////////////////////////////////////////////
// macro for different type of flgr1d_raster_slide_structuring_function
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(dtype,getnhbop) \
  int j,w;								\
  fgINT32 *psemap = (fgINT32 *) semap->array;				\
  FLGR_Vector *result;							\
  FLGR_Data1D *nhbrs;							\
  FLGR_NhbBox1D *extr;							\
  int dynsew;								\
  int spp = datsrc->spp;						\
  int type = datsrc->type;						\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  w=datsrc->length;							\
									\
  result = flgr_vector_create(datsrc->spp,datsrc->type);		\
									\
  for(j=0 ; j<w ; j++) {						\
    dynsew = flgr_get_array_fgINT32(psemap, j);				\
									\
    nhbrs = flgr1d_create_neighborhood((int) dynsew,spp,type,shape);	\
    extr = flgr1d_create_neighbor_box(nhbrs);				\
									\
    getnhbop##_##dtype(extr,datsrc,nhbrs,j);				\
    (*computeNhb)(result,extr);						\
    flgr1d_set_data_vector_##dtype(datdest,j,result);			\
									\
    flgr1d_destroy(nhbrs);						\
    flgr1d_destroy_neighbor_box(extr);					\
									\
  }									\
									\
  flgr_vector_destroy(result);						\
									\
  return



void flgr1d_raster_slide_structuring_function_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						    FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgBIT,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						      FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgUINT8,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						       FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgUINT16,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						       FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgUINT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						     FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgINT8,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						      FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgINT16,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						      FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgINT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
							FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgFLOAT32,flgr1d_get_neighborhood);
}
void flgr1d_raster_slide_structuring_function_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
							FLGR_Data1D *semap, FLGR_Shape shape, FLGR_ComputeNhb1D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_STRUCTURING_FUNCTION_1D(fgFLOAT64,flgr1d_get_neighborhood);
}

////////////////////////////////////////////////////////////////////////////
/*! Slide a resizable kernel on a FLGR_Data1D in a raster scan way
 *  @param datdest : pointer to destination image
 *  @param datsrc : pointer to source image
 *  @param semap : pointer to image containing each kernel topology information (fgINT32 type)
 *  @param shape : FLGR_DISC, FLGR_RECT, ...
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is made
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_raster_slide_structuring_function(FLGR_Data1D *datdest, FLGR_Data1D *datsrc, 
						  FLGR_Data1D *semap, FLGR_Shape shape, 
						  FLGR_ComputeNhb1D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (semap==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(semap->type != FLGR_INT32) {
    POST_ERROR("semap type must be FLGR_INT32\n");
    return FLGR_RET_PARAM_ERROR;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;
  if((ret = flgr1d_is_data_same_length(datdest,semap)) != FLGR_RET_OK) {
    POST_ERROR("semap size does not correspond to datdest or datsrc size\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_raster_slide_structuring_function,datdest,datsrc,
			  semap,shape,computeNhb);

}




////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_TYPE
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(dtype,get_nhb_op)		\
  int i,j,w,h,spp_map=semap->spp;					\
  int spp=datsrc->spp;							\
  int type=datsrc->type;						\
  fgINT32 *psemap;							\
  FLGR_Vector *result;							\
  FLGR_Data2D *nhbtmp,*nhbrs;						\
  FLGR_NhbBox2D *extr;							\
  int dynsew, dynseh, dynseteta;					\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  w=datsrc->size_x;							\
  h=datsrc->size_y;							\
									\
  result = flgr_vector_create(spp,type);				\
									\
									\
  for(i=0 ; i<h; i++) {							\
    psemap = (fgINT32 *) semap->array[i];				\
									\
    for(j=0 ; j<w ; j++) {						\
									\
      if(spp_map<=1) {							\
 	dynsew = flgr_get_array_fgINT32(psemap,j);			\
	dynsew = ((dynsew>>1)<<1)+1;					\
	nhbrs = flgr2d_create_neighborhood(dynsew,dynsew,spp,		\
					   type,shape,FLGR_8_CONNEX);	\
      }else if(spp_map<=2) {						\
 	dynsew = flgr_get_array_fgINT32(psemap,j*spp_map);		\
 	dynseh = flgr_get_array_fgINT32(psemap,j*spp_map+1);		\
 	dynsew = ((dynsew>>1)<<1)+1;					\
	dynseh = ((dynseh>>1)<<1)+1;					\
	nhbrs = flgr2d_create_neighborhood(dynseh,dynsew,spp,		\
					   type,shape,FLGR_8_CONNEX);	\
      }else {								\
 	dynsew = flgr_get_array_fgINT32(psemap,j*spp_map);		\
 	dynseh = flgr_get_array_fgINT32(psemap,j*spp_map+1);		\
	dynseteta = flgr_get_array_fgINT32(psemap,j*spp_map+2);		\
 	dynsew = (dynsew<<1)+1;						\
	dynseh = (dynseh<<1)+1;						\
	nhbrs = flgr2d_create_##dtype(dynseh,dynsew,spp,		\
				      shape,FLGR_8_CONNEX);		\
  	nhbtmp = flgr2d_create_##dtype(dynseh,dynsew,spp,		\
				       shape,FLGR_8_CONNEX);		\
	flgr2d_fill_neighborhood_##dtype(nhbtmp,shape,dynsew,dynseh);	\
	flgr2d_rotate_center_##dtype(nhbrs,nhbtmp,dynseteta);		\
	flgr2d_destroy(nhbtmp);						\
      }									\
									\
      extr = flgr2d_create_neighbor_box(nhbrs);				\
      									\
      get_nhb_op##_##dtype(extr,datsrc,nhbrs,i,j);			\
									\
      (*computeNhb)(result,extr);					\
									\
      flgr2d_set_data_vector_##dtype(datdest,i,j,result);		\
									\
      flgr2d_destroy_neighbor_box(extr);				\
      flgr2d_destroy(nhbrs);						\
    }									\
  }									\
									\
  flgr_vector_destroy(result);						\
									\
  return




void flgr2d_raster_slide_structuring_function_fgBIT(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						    FLGR_Data2D *semap, FLGR_Shape shape, 
						    FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgBIT,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgUINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						      FLGR_Data2D *semap, FLGR_Shape shape, 
						      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgUINT8,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgUINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						       FLGR_Data2D *semap, FLGR_Shape shape, 
						       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgUINT16,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgUINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						       FLGR_Data2D *semap, FLGR_Shape shape, 
						       FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgUINT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						     FLGR_Data2D *semap, FLGR_Shape shape, 
						     FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgINT8,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						      FLGR_Data2D *semap, FLGR_Shape shape, 
						      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgINT16,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						      FLGR_Data2D *semap, FLGR_Shape shape, 
						      FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgINT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgFLOAT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
							FLGR_Data2D *semap, FLGR_Shape shape,
							FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgFLOAT32,flgr2d_get_neighborhood);
}
void flgr2d_raster_slide_structuring_function_fgFLOAT64(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
							FLGR_Data2D *semap, FLGR_Shape shape, 
							FLGR_ComputeNhb2D computeNhb) {
  FLGR_MACRO_RASTER_SLIDE_FUNCTION_2D(fgFLOAT64,flgr2d_get_neighborhood);
}

////////////////////////////////////////////////////////////////////////////
/*! Slide a resizable kernel on a FLGR_Data2D in a raster scan way
 *
 *  SE width for each pixel are stored in semap. semap could have one to three channel
 *
 *  - If semap->spp==1 then 
 *      - Channel 1 indicates the width of the square around the shape
 *
 *  - If semap->spp==2 then  
 *      - Channel 1 indicates the width of the rectangle around the shape
 *      - Channel 2 indicates the height of the rectangle around the shape
 *
 *  - If semap->spp==3 then  
 *      - Channel 1 indicates the width of the rectangle around the shape
 *      - Channel 2 indicates the height of the rectangle around the shape
 *      - Channel 3 indicates the rotation angle of the shape [-180,180] degrees
 *
 *  @param *datdest : image output
 *  @param *datsrc : image input
 *  @param *semap : maps of the neighborhood size evolution
 *  @param shape : shape
 *  @param computeNhb : Pointer to a function where neighborhood or convolution computation is done
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_raster_slide_structuring_function(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, 
						  FLGR_Data2D *semap, FLGR_Shape shape, 
						  FLGR_ComputeNhb2D computeNhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((datdest==NULL) || (datsrc==NULL) || (semap==NULL)) {
    POST_ERROR("Null objects\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(semap->type != FLGR_INT32) {
    POST_ERROR("semap type must be FLGR_INT32\n");
    return FLGR_RET_PARAM_ERROR;
  }

  if((ret = flgr2d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;
  if((ret = flgr2d_is_data_same_size(datdest,semap)) != FLGR_RET_OK) {
    POST_ERROR("semap size does not correspond to datdest or datsrc size\n");
    return ret;
  }


  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr2d_raster_slide_structuring_function,datdest,datsrc,
			  semap,shape,computeNhb);

}






//! @}
